﻿#region Copyright

// The contents of this file are subject to the Mozilla Public License
//  Version 1.1 (the "License"); you may not use this file except in compliance
//  with the License. You may obtain a copy of the License at
//  
//  http://www.mozilla.org/MPL/
//  
//  Software distributed under the License is distributed on an "AS IS"
//  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
//  License for the specific language governing rights and limitations under 
//  the License.
//  
//  The Initial Developer of the Original Code is Robert Smyth.
//  Portions created by Robert Smyth are Copyright (C) 2008.
//  
//  All Rights Reserved.

#endregion

using System;
using System.Collections.Generic;
using NUnitGrid.Framework.Env;
using NUnitGrid.Framework.Logging;
using NUnitGrid.Framework.Pipes;
using NUnitGrid.Node.Runner;
using NUnitGrid.Protocol;
using NUnitGrid.Protocol.Responses;


namespace NUnitGrid.Node.Plugins.ServerLink.Protocol
{
    public class RunAsProcessCommandHandler : IProtocolCommandHandler, IRunProgressListener
    {
        private readonly ILogger logger;
        private readonly IPipe pipe;
        private readonly IRunner runner;
        private int transactionID;

        public RunAsProcessCommandHandler(IPipe pipe, IRunner runner, ILogger logger)
        {
            this.pipe = pipe;
            this.runner = runner;
            this.logger = logger;
        }

        public bool CanHandle(string commandMessage)
        {
            return commandMessage.StartsWith("Command.RunOnGrid.AsProcess(");
        }

        public void Handle(string commandMessage)
        {
            logger.Info.Write("Starting run as process task.");

            var parser = new ProtocolMessageParser(commandMessage);
            transactionID = parser.GetTransactionID();
            var fileName = parser.GetValue("FileName");
            var workingDirectory = parser.GetValue("WorkingDirectory");
            var commandLine = parser.GetValue("CommandLine");
            var timeLimit = TimeSpan.Parse(parser.GetValue("TimeLimit"));

            IProtocolMessageParsing nestedPropertiesParser =
                new ProtocolMessageParser(parser.GetValue("EnvironmentVariables"));
            var enviromentVariableNames = new List<string>(nestedPropertiesParser.GetPropertyNames());

            var variables = new List<EnvironmentVariable>();
            foreach (var variableName in enviromentVariableNames)
            {
                var name = variableName.Trim();
                var value = nestedPropertiesParser.GetValue(name);
                variables.Add(new EnvironmentVariable(name, value));
            }

            try
            {
                runner.Run(this, workingDirectory, fileName, commandLine, timeLimit, variables.ToArray());
            }
            catch (Exception exception)
            {
                var message = string.Format("{0} exception thrown by process: '{1}'", exception, exception.Message);
                ((IRunProgressListener) this).OnCompleted(message, false, true);
                logger.Warning.Write(string.Format("Ran as process task threw exception - {0}", message));
                throw;
            }
        }

        void IRunProgressListener.OnCompleted(string textOutput, bool succeeded, bool taskError)
        {
            if (!succeeded || taskError)
            {
                logger.Warning.Write("Run as process task failed.\n\n{0}", textOutput);
            }
            else
            {
                logger.Info.Write("Run as process task succeeded.");
            }

            var response = new ProtocolAppResponseMessage("RunOnGrid.AsProcess", transactionID);
            response.AddProperty("Succeeded", succeeded && !taskError);
            response.AddProperty("MachineName", Environment.MachineName);
            response.AddProperty("TextOutput", textOutput);
            pipe.SendMessage(response.ToString());
        }
    }
}